package com.whosly.strategy.factory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import lombok.Data;

import org.apache.commons.collections4.CollectionUtils;

import com.whosly.strategy.IStrategy;
import com.whosly.strategy.spring.ManageSpringBeans;

/**
 *
 *
 * @category 策略管理器，用于策略管理，检查常用策略管理，如默认方法等
 *
 * @author <a href="mailto:yueny09@126.com"> 袁洋 2014年11月26日
 */
public class StrategyFactoryService implements IStrategyFactory {
	@Data
	private static class StrategyBo {
		private final Object condition;
		private final IStrategy<?> strategy;
	}

	// XXX 测试用例如何写
	private final Map<Class<?>, Collection<StrategyBo>> strategyMap = new HashMap<Class<?>, Collection<StrategyBo>>();

	private <T extends IStrategy<D>, D> Collection<StrategyBo> findStrategys(
			final Class<T> strategyClass) {
		final Collection<StrategyBo> strategys = strategyMap.get(strategyClass);
		if (CollectionUtils.isNotEmpty(strategys)) {
			return strategys;
		}

		final Collection<T> beans = ManageSpringBeans.getBeans(strategyClass)
				.values();
		if (CollectionUtils.isEmpty(beans)) {
			return null;
		}

		final Collection<StrategyBo> newList = new ArrayList<StrategyFactoryService.StrategyBo>();
		for (final T t : beans) {
			newList.add(new StrategyBo(t.getCondition(), t));
		}

		strategyMap.put(strategyClass, newList);
		return newList;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.yueny.codelets.support.strategy.IStrategyFactory#getStrategy(java
	 * .lang.Class, java.lang.Object)
	 */
	@Override
	public <D, T extends IStrategy<D>> T getStrategy(
			final Class<T> strategyClass, final D condition) {
		final Collection<StrategyBo> strategys = findStrategys(strategyClass);
		if (CollectionUtils.isEmpty(strategys)) {
			return null;
		}

		for (final StrategyBo strategyBo : strategys) {
			// TODO 此处可以考虑使用filter替换简单的等号
			if (strategyBo.getCondition() == condition) {
				@SuppressWarnings("unchecked")
				final T strategy = (T) strategyBo.getStrategy();
				// TODO 此处考虑使用cglib扩展
				return strategy;
			}
		}
		return null;
	}

}
